/************************************************************************/
// Copyright (C) 2016, han_gangbiao. All rights reserved.
// Use of this source code is governed by a GPL-v2 license that can be found in the License file.
// 
// [Time]:      2016-1-4 21:53:17
// [Author]:    han_gangbiao [http://my.oschina.net/jackhen]
// [Info]:      
/************************************************************************/

#ifndef INCLUDE_PROTOCOL_NET_BINARY_PDU_H_
#define INCLUDE_PROTOCOL_NET_BINARY_PDU_H_


#include "base/baseheader.h"
#include "base/xrefptr.h"
#include <vector>

/*
    |----------length(32bits)------------|
    |--version(16bits)--|--unit(16bits)--|
    |----flag(16bits)---|--oper(16bits)--|
    |-------------seq(32bits)------------|
    |---------reserved(32bits)-----------|
    |================body================|
    |================body================|
    |================body================|

*/

typedef struct PduHeader {
    uint32 length;      // the whole pdu length
    uint16 version;     // pdu version
    uint16 unit;        // owner unit
    uint16 flag;        // pdu flag(REQ/RESP..)
    uint16 operation;   // operation
    uint32 seq;         // pdu sequence
    uint32 reserved;    // reserved
}PduHeader_t; //160 bits = 20 bytes

class NetBinaryPdu : public smart::refobj_t
{
public:
    NetBinaryPdu();
protected:
    virtual ~NetBinaryPdu(); //should not to delete

public:
    static smart::ref_ptr<NetBinaryPdu> createPduFromStream(const char* data, int len, int& rPduLen);
public: //header
    int getHeaderLen() const;

    uint32 getPduLength() const;
    uint16 getVersion() const;
    uint16 getUnit() const;
    uint16 getFlag() const;
    uint16 getOperation() const;
    uint32 getSeq() const;
    uint32 getReserved() const;

    void setUnit(uint16 unit);
    void setFlag(uint16 flag);
    void setOperation(uint16 operation);
    void setSeq(uint32 seq);

protected:
    void setPduLength(uint32 length);
    void setVersion(uint16 version);
    void setReserved(uint32 reserved);

public: //body
    const char* getBody() const;
    int getBodyLen() const;

    int setBody(const char* data, int len = -1);

public:
    virtual const char* toStream();
    virtual int fromStream(const char* data, int len);

    const char* getBinaryStream() const;
    int getBinaryStreamLength() const;

protected: //byte-stream [big endian]
    static int16 readInt16(const char* buf);
    static uint16 readUInt16(const char* buf);
    static int32 readInt32(const char* buf);
    static uint32 readUInt32(const char* buf);
    static void writeInt16(char* buf, int16 data);
    static void writeUInt16(char* buf, uint16 data);
    static void writeInt32(char* buf, int32 data);
    static void writeUInt32(char* buf, uint32 data);
protected:
    PduHeader_t m_header;
    std::vector<char> m_body;
    std::vector<char> m_stream;

};

class NetBinaryPduResponse;
class NetBinaryPduRequest : public NetBinaryPdu
{
public:
    NetBinaryPduRequest();
protected:
    virtual ~NetBinaryPduRequest(); //should not to delete

public:
    smart::ref_ptr<NetBinaryPduResponse> createResponse();

public:
    virtual const char* toStream();
    virtual int fromStream(const char* data, int len);
};

class NetBinaryPduResponse : public NetBinaryPdu
{
public:
    NetBinaryPduResponse();
protected:
    virtual ~NetBinaryPduResponse(); //should not to delete

public:
    virtual const char* toStream();
    virtual int fromStream(const char* data, int len);

};


#endif //~INCLUDE_PROTOCOL_NET_BINARY_PDU_H_
